(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory()
        : typeof define === 'function' && define.amd ? define(factory)
            : (global = global || self, global.tpUtils = factory());
}(this, function () {
    function parseTime(time, cFormat) {
        if (arguments.length === 0) {
            return null;
        }
        const format = cFormat || '{y}-{m}-{d} {h}:{i}:{s}';
        const date = getDateObj(time);
        const formatObj = {
            y: date.getFullYear(),
            m: date.getMonth() + 1,
            d: date.getDate(),
            h: date.getHours(),
            i: date.getMinutes(),
            s: date.getSeconds(),
            a: date.getDay()
        };
        const timeStr = format.replace(/{(y|m|d|h|i|s|a)+}/g, (result, key) => {
            let value = formatObj[key];
            // Note: getDay() returns 0 on Sunday
            if (key === 'a') {
                return ['日', '一', '二', '三', '四', '五', '六'][value];
            }
            if (result.length > 0 && value < 10) {
                value = '0' + value;
            }
            return value || 0;
        });
        return timeStr;
    }
    function getDateObj(time) {
        let date;
        if (typeof time === 'object') {
            date = time;
        } else {
            if (typeof time === 'string') {
                if (/^[0-9]+$/.test(time)) {
                    time = parseInt(time);
                } else {
                    time = time.replace(/\-/g, '/');
                }
            }
            if ((typeof time === 'number') && (time.toString().length === 10)) {
                time = time * 1000;
            }
            date = new Date(time);
        }
        return date;
    }
    function getFormatterText(text, number, separator) {
        number = number || 3;
        separator = separator || '\n'; // 或 <br>
        var newParamsName = ''; // 返回文字格式
        var paramsNameNumber = text.length; // 获取显示文字长度
        var rowNumber = Math.ceil(paramsNameNumber / number); // 最多能显示几行
        if (paramsNameNumber > number) {
            // 如果长度大于每行最多显示的字数
            for (var p = 0; p < rowNumber; p++) {
                // 循环次数就是行数
                var tempStr = ''; // 每次截取的字符
                var start = p * number; // 截取的起点
                var end = start + number; // 截取的终点
                if (p == rowNumber - 1) {
                    // 最后一行就不换行了
                    tempStr = text.substring(start);
                } else {
                    tempStr = text.substring(start, end) + separator;
                }
                newParamsName += tempStr; // 拼接字符串
            }
        } else {
            newParamsName = text; // 如果小于每行最多显示的字数就返回原来的字符串
        }
        return newParamsName;
    }
    function observerDomResize(dom, callback) {
        const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;

        const observer = new MutationObserver(callback);

        observer.observe(dom, { attributes: true, attributeFilter: ['style'], attributeOldValue: true });

        return observer;
    }
    function getMatchRegionValue(regionCode) {
        const matchArr = regionCode.match(/0+$/);
        let len = 0;
        let value = '';
        if (matchArr) {
            len = matchArr[0].length;
            len = len % 2 === 0 ? len : len - 1; // 必须为偶数
            len = len > 0 ? len : 0;
        }
        if (len) {
            value = regionCode.slice(0, -len);
        } else {
            value = regionCode;
        }
        return value;
    }
    function deepClone(object, recursion = false) {
        if (!object) return object;

        const { parse, stringify } = JSON;

        if (!recursion) return parse(stringify(object));

        const clonedObj = object instanceof Array ? [] : {};

        if (object && typeof object === 'object') {
            for (const key in object) {
                if (object.hasOwnProperty(key)) { /* eslint-disable-line */
                    if (object[key] && typeof object[key] === 'object') {
                        clonedObj[key] = deepClone(object[key], true);
                    } else {
                        clonedObj[key] = object[key];
                    }
                }
            }
        }

        return clonedObj;
    }

    /**
     * 获取两个日期之间的日期
     * @param start
     * @param end
     * @param type 1：不包含起始日期，包含结束日期 2：包含起始日期，不包含结束日期 3：包含起始日期，包含结束日期
     * @returns {date[]}
     */
    function getBetweenDateStr(start, end, type = 1) {
        const startTime = getDateObj(start);
        const endTime = getDateObj(end);
        const arr = [];
        if (type === 1) {
            while ((endTime.getTime() - startTime.getTime()) > 0) {
                startTime.setDate(startTime.getDate() + 1);
                arr.push(parseTime(startTime, '{y}-{m}-{d}'));
            }
        } else if (type === 2) {
            while ((endTime.getTime() - startTime.getTime()) > 0) {
                arr.push(parseTime(startTime, '{y}-{m}-{d}'));
                startTime.setDate(startTime.getDate() + 1);
            }
        } else if (type === 3) {
            while ((endTime.getTime() - startTime.getTime()) >= 0) {
                arr.push(parseTime(startTime, '{y}-{m}-{d}'));
                startTime.setDate(startTime.getDate() + 1);
            }
        }
        return arr;
    }

    /**
     * 获得每月的总天数
     * @param {Number} year
     * @param {Number} m
     * @return {Number}
     */
    function daysInMonth(year, month) {
        return /3|5|8|10/.test(month) ? 30 : month === 1 ? (!(year % 4) && year % 100) || !(year % 400) ? 29 : 28 : 31;
    }

    /**
     * 比较时间大小
     */
    function dateCompare(startDate, endDate) {
        // 计算截止时间
        startDate = new Date(startDate.replace('-', '/').replace('-', '/'));
        // 计算详细项的截止时间
        endDate = new Date(endDate.replace('-', '/').replace('-', '/'));
        if (startDate <= endDate) {
            return true;
        } else {
            return false;
        }
    }

    // 数字
    function isNumber(value) {
        if (isNaN(value)) {
            return false;
        }
        return typeof +value === 'number';
    }

    function toNumber(value, fractionDigits = 2) {
        return isNumber(value) ? Number(value).toFixed(fractionDigits) - 0 : 0;
    }

    // 可以将数字转换成中文大写的表示，处理到万级别，例如 toChineseNum(12345)，返回 一万二千三百四十五
    function toChineseNum(num) {
        const changeNum = ['零', '一', '二', '三', '四', '五', '六', '七', '八', '九']; // changeNum[0] = "零"
        const unit = ['', '十', '百', '千', '万'];
        num = parseInt(num);
        const getWan = (temp) => {
            const strArr = temp.toString().split('').reverse();
            let newNum = '';
            for (let i = 0; i < strArr.length; i++) {
                newNum = (i == 0 && strArr[i] == 0 ? '' : (i > 0 && strArr[i] == 0 && strArr[i - 1] == 0 ? '' : changeNum[strArr[i]] + (strArr[i] == 0 ? unit[0] : unit[i]))) + newNum // eslint-disable-line
            }
            return newNum;
        };
        const overWan = Math.floor(num / 10000);
        let noWan = num % 10000;
        if (noWan.toString().length < 4) noWan = '0' + noWan;
        return overWan ? getWan(overWan) + '万' + getWan(noWan) : getWan(num);
    }

    function getDataMap(data, key) {
        return data.reduce((pre, cur) => {
            if (pre[cur[key]]) {
                pre[cur[key]].push(cur);
            } else {
                pre[cur[key]] = [cur];
            }
            return pre;
        }, {});
    }

    // 接口请求
    function request(api, param) {
        return new Promise((resolve, reject) => {
            tpHttp.post(this, api, { param: JSON.stringify(param || {}) }, (data, code, mesage) => {
                if (code == 0) {
                    resolve(data);
                } else {
                    ELEMENT.Message.error(mesage || '抱歉，出现了一个错误');
                    reject();
                }
            });
        });
    }

    /**
     * @desc 函数防抖
     * @param func 函数
     * @param wait 延迟执行毫秒数
     * @param immediate true 表立即执行，false 表非立即执行
     */
    function debounce(func, wait, immediate) {
        let timeout, result;

        const debounced = function () {
            const context = this;
            const args = arguments;

            if (timeout) {
                clearTimeout(timeout);
            }
            if (immediate) {
                // 如果已经执行过，不再执行
                const callNow = !timeout;
                timeout = setTimeout(function () {
                    timeout = null;
                }, wait);
                if (callNow) {
                    result = func.apply(context, args);
                }
            } else {
                timeout = setTimeout(function () {
                    func.apply(context, args);
                }, wait);
            }

            return result;
        };

        debounced.cancel = function () {
            clearTimeout(timeout);
            timeout = null;
        };

        return debounced;
    }

    // 获取图形中心坐标
    function calculateCenter(lnglatarr) {
        var total = lnglatarr.length;
        var X = 0; var Y = 0; var Z = 0;

        lnglatarr.map(arr => ({ lng: arr[0], lat: arr[1] })).forEach(function (lnglat) {
            var lng = lnglat.lng * Math.PI / 180;
            var lat = lnglat.lat * Math.PI / 180;
            var x, y, z;
            x = Math.cos(lat) * Math.cos(lng);
            y = Math.cos(lat) * Math.sin(lng);
            z = Math.sin(lat);
            X += x;
            Y += y;
            Z += z;
        });

        X = X / total;
        Y = Y / total;
        Z = Z / total;

        var Lng = Math.atan2(Y, X);
        var Hyp = Math.sqrt(X * X + Y * Y);
        var Lat = Math.atan2(Z, Hyp);

        // return new AMap.LngLat(Lng * 180 / Math.PI, Lat * 180 / Math.PI);
        return [Lng * 180 / Math.PI, Lat * 180 / Math.PI];
    }

    function deepMerge(target, merged) {
        for (const key in merged) {
            if (target[key] && typeof target[key] === 'object') {
                deepMerge(target[key], merged[key]);

                continue;
            }

            if (typeof merged[key] === 'object') {
                target[key] = deepClone(merged[key], true);

                continue;
            }

            target[key] = merged[key];
        }

        return target;
    }


    function getDataModelLabel(items, targetValue) {
        let [item = {}] = items.filter(t => t.value == targetValue);
        return item.label || "";
    }

    return {
        parseTime,
        getDateObj,
        getFormatterText,
        observerDomResize,
        getMatchRegionValue,
        deepClone,
        getBetweenDateStr,
        daysInMonth,
        dateCompare,
        isNumber,
        toNumber,
        toChineseNum,
        getDataMap,
        request,
        debounce,
        calculateCenter,
        deepMerge,
        getDataModelLabel,
    };
}));
